package fd.sudoku.utility;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import fd.sudoku.data.SudokuMap;
import fd.sudoku.data.SudokuNumber;

public class SudokuCheck {

	public static final int LINESIZE = 9;

	public static final int ROWSIZE = 9;
	
	public static final int SIZEOFBLOCK = 9;
	
	public static final int BLOCKSIZE = 9;

	static public boolean checkMap(SudokuMap maps) {
		boolean valide = false;
		valide = checkEachLine(maps) & checkEachRow(maps);
		return valide;
	}

	static public boolean checkEachLine(SudokuMap maps) {
		boolean valide = true;
		for (int i = 1; i <= LINESIZE; i++) {
			ArrayList<Integer> lists = new ArrayList<Integer>();
			for (int j = 1; j <= ROWSIZE; j++) {
				SudokuNumber sudokuNumber = maps.get(i, j);
				if (sudokuNumber != null && sudokuNumber.getValue() > 0) {
					lists.add(sudokuNumber.getValue());
				} else if (sudokuNumber == null) {
					System.err.println(String.valueOf(i * 10 + j)
							+ " has no value!");
					return false;
				} else {
					return false;
				}
			}
			if (hasDuplicate(lists)) {
				return false;
			}

		}
		return valide;
	}

	static public boolean checkEachRow(SudokuMap maps) {
		boolean valide = true;
		for (int i = 1; i <= ROWSIZE; i++) {
			ArrayList<Integer> lists = new ArrayList<Integer>();
			for (int j = 1; j <= LINESIZE; j++) {
				SudokuNumber sudokuNumber = maps.get(j, i);
				if (sudokuNumber != null && sudokuNumber.getValue() > 0) {
					lists.add(sudokuNumber.getValue());
				} else if (sudokuNumber == null) {
					System.err.println(String.valueOf(i * 10 + j)
							+ " has no value!");
					return false;
				} else {
					return false;
				}
			}
			if (hasDuplicate(lists)) {
				return false;
			}

		}
		return valide;
	}

	public static <T> boolean hasDuplicate(Collection<T> list) {
		Set<T> set = new HashSet<T>();
		// Set#add returns false if the set does not change, which
		// indicates that a duplicate element has been added.
		for (T each : list) {
			if (!set.add(each)) {
				return true;
			}
		}
		return false;
	}

	public static ArrayList<Integer> getFullPossibleValues() 
	{
		ArrayList<Integer> possibleValues = new ArrayList<Integer>();
		for(int i = 1 ; i<=9 ; i++)
		{
			possibleValues.add(i);
		}
		return possibleValues;
	}

}
